package com.ccc.boot.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ccc.boot.base.BaseServiceImpl;
import com.ccc.boot.constant.DictConstant;
import com.ccc.boot.easypoi.util.MyExcelUtils;
import com.ccc.boot.easypoi.util.MyFileUtils;
import com.ccc.boot.easypoi.util.ZipUtils;
import com.ccc.boot.exception.BusinessException;
import com.ccc.boot.pojo.Query;
import com.ccc.boot.pojo.UserVO;
import com.ccc.boot.response.ResponseCode;
import com.ccc.boot.system.entity.RelUserRole;
import com.ccc.boot.system.entity.SysDept;
import com.ccc.boot.system.entity.SysUser;
import com.ccc.boot.system.mapper.SysDeptMapper;
import com.ccc.boot.system.mapper.SysUserMapper;
import com.ccc.boot.system.pojo.ExportUserData;
import com.ccc.boot.system.pojo.PasswordParam;
import com.ccc.boot.system.pojo.RelateUserVO;
import com.ccc.boot.system.pojo.SysUserData;
import com.ccc.boot.system.service.RelUserRoleService;
import com.ccc.boot.system.service.SysFileService;
import com.ccc.boot.system.service.SysUserService;
import com.ccc.boot.system.util.DesensitizeUtil;
import com.ccc.boot.system.util.PasswordUtils;
import com.ccc.boot.util.Base64Utils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 人员服务层实现类
 *
 * @author superC
 * @version 0.1.0
 * @date 2022/3/23
 */

@Service
public class SysUserSerivceImpl extends BaseServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Autowired
    private SysFileService fileService;

    @Autowired
    private RelUserRoleService relUserRoleService;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Override
    public boolean insert(SysUser entity) {
        // 验证系统登录名是否已存在
        checkUsernameIsExist(entity.getUsername());

        // 验证手机号码是否已存在
        checkPhoneIsExist(entity.getPhone());

        if (entity.getPassword() == null) {
            // 设置默认密码
            entity.setPassword(PasswordUtils.defaultPwd());
        }
        if (entity.getPhotoId() == null) {
            // 设置默认头像
            entity.setPhotoId(1L);
        }
        return super.insert(entity);
    }

    private void checkPhoneIsExist(String phone) {
        if (StringUtils.isEmpty(phone)) {
            throw new BusinessException(ResponseCode.USER_PHONE_HAS_REQUIRED);
        }
        SysUser user = getByPhone(phone);
        if (user != null) {
            throw new BusinessException(ResponseCode.USER_PHONE_IS_EXISTED);
        }
    }

    private void checkUsernameIsExist(String username) {
        if (StringUtils.isEmpty(username)) {
            throw new BusinessException(ResponseCode.USER_ACCOUNT_HAS_REQUIRED);
        }
        SysUser user = getByUsername(username);
        if (user != null) {
            throw new BusinessException(ResponseCode.USER_IS_EXISTED);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(SysUser entity) {
        SysUser user = baseMapper.selectById(entity.getId());
        if (user != null) {
            // 判断登录账户是否修改
            checkUsernameIsUpdate(user.getUsername(), entity.getUsername());

            // 判断手机号码是否修改
            checkPhoneIsUpdate(user.getPhone(), entity.getPhone());

            /**
             * 修改用户表
             */
            user.setUsername(entity.getUsername());
            user.setRealName(entity.getRealName());
            user.setPhotoId(entity.getPhotoId());
            user.setDeptId(entity.getDeptId());
            user.setGender(entity.getGender());
            user.setType(entity.getType());
            user.setPhone(entity.getPhone());
            user.setEmail(entity.getEmail());
            user.setAge(entity.getAge());
            user.setBirthday(entity.getBirthday());
            user.setAddress(entity.getAddress());
            user.setStatus(entity.getStatus());
            user.setMemo(entity.getMemo());

            return super.updateById(user);
        } else {
            throw new BusinessException(ResponseCode.DATA_GET_ERROR);
        }
    }

    private void checkPhoneIsUpdate(String source, String target) {
        if (StringUtils.isEmpty(target)) {
            throw new BusinessException(ResponseCode.USER_PHONE_HAS_REQUIRED);
        }
        if (StringUtils.equals(source, target)) {
            return;
        }
        checkPhoneIsExist(target);
    }

    private void checkUsernameIsUpdate(String source, String target) {
        if (StringUtils.isEmpty(target)) {
            throw new BusinessException(ResponseCode.USER_ACCOUNT_HAS_REQUIRED);
        }
        if (StringUtils.equals(source, target)) {
            return;
        }
        checkUsernameIsExist(target);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Long id) {
        try {
            if (checkId(id)) {
                SysUser user = baseMapper.selectById(id);

                // 删除用户角色中间表
                relUserRoleService.deleteByUserId(id);

                // 删除图片
                if (user.getPhotoId() != null) {
                    fileService.delete(user.getPhotoId());
                }

                // 删除用户
                return super.removeById(id);
            } else {
                throw new BusinessException(ResponseCode.RESULT_DATA_NONE);
            }
        } catch (Exception e) {
            logger.error("【捕获异常-删除操作】\r\n异常记录：", e);
            //手工回滚异常
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new BusinessException(ResponseCode.DATA_DELETE_FAILURE);
        }
    }

    /**
     * 切换部门
     */
    @Override
    public boolean updateDept(Long id, Long deptId) {
        boolean exist = super.checkId(id);
        if (!exist) {
            throw new BusinessException(ResponseCode.RESULT_DATA_NONE);
        }
        LambdaUpdateWrapper<SysUser> wrapper = new LambdaUpdateWrapper<>();
        // 条件
        wrapper.eq(SysUser::getId, id);
        // 修改字段
        wrapper.set(SysUser::getDeptId, deptId);
        return super.update(wrapper);
    }

    @Override
    public boolean updatePassword(PasswordParam param) {
        if (StringUtils.isEmpty(param.getPassword()) || StringUtils.isEmpty(param.getConfirmPassword())) {
            throw new BusinessException(ResponseCode.USER_PASSWORD_NOT_NULL);
        }
        if (!StringUtils.equals(param.getPassword(), param.getConfirmPassword())) {
            throw new BusinessException(ResponseCode.USER_PASSWORD_NOT_EQUALS);
        }
        // 加密
        String password = PasswordUtils.bcrypt(param.getPassword());

        LambdaUpdateWrapper<SysUser> wrapper = new LambdaUpdateWrapper<>();
        // 条件
        wrapper.eq(SysUser::getId, param.getUserId());
        // 修改字段
        wrapper.set(SysUser::getPassword, password);
        return super.update(wrapper);
    }

    /**
     * 清除照片
     */
    @Override
    public boolean removeImage(Long id) {
        boolean exist = super.checkId(id);
        if (!exist) {
            throw new BusinessException(ResponseCode.RESULT_DATA_NONE);
        }
        LambdaUpdateWrapper<SysUser> wrapper = new LambdaUpdateWrapper<>();
        // 条件
        wrapper.eq(SysUser::getId, id);
        // 修改字段
        wrapper.set(SysUser::getPhotoId, null);
        return super.update(wrapper);
    }

    @Override
    public IPage<UserVO> pageUser(Query query) {
        IPage<UserVO> iPage = getPageUser(query);
        /**
         * 对数据进行补充
         */
        List<UserVO> resultList = iPage.getRecords().stream()
                .map(vo -> {
                    // 图片
                    if (vo.getPhotoId() != null) {
                        String base64 = fileService.getImage(vo.getPhotoId());
                        vo.setFaceUri(base64);
                    }
                    /*
                        重要信息脱敏
                     */
                    String name = DesensitizeUtil.desensitizedName(vo.getRealName());
                    vo.setRealName(name);
                    String phone = DesensitizeUtil.desensitizedPhone(vo.getPhone());
                    vo.setPhone(phone);

                    return vo;
                }).collect(Collectors.toList());
        iPage.setRecords(resultList);
        return iPage;
    }

    private IPage<UserVO> getPageUser(Query query) {
        Page<UserVO> page = new Page<>(query.getCurrent(), query.getSize());
        QueryWrapper<UserVO> wrapper = new QueryWrapper<>();
        query.forEach((column, value) -> {
            // 非空，进行模糊查询
            if (value != null && value != "") {
                if (StringUtils.equals("dept_id", column)) {
                    wrapper.eq(column, value);
                } else {
                    wrapper.like(column, value);
                }
            }
        });
        return baseMapper.pageUser(page, wrapper);
    }

    @Override
    public List<UserVO> getEnabledUsers(UserVO query) {
        query.setStatus(DictConstant.USER_STATUS_OK);
        List<UserVO> list = baseMapper.getEnabledUsers(query);
        return list;
    }

    @Override
    public IPage<UserVO> getUsersByRole(Long roleId, Query query) {
        Page<UserVO> page = new Page<>(query.getCurrent(), query.getSize());
        return baseMapper.pageUsersByRole(page, DictConstant.USER_STATUS_OK, roleId);
    }

    @Override
    public IPage<RelateUserVO> getUsersByDept(Long roleId, Query query) {
        IPage<UserVO> iPage = getPageUser(query);
        /**
         * 对数据进行补充
         */
        Page<RelateUserVO> result = new Page<>();
        List<RelateUserVO> resultList = iPage.getRecords().stream()
                .map(vo -> {
                    RelateUserVO data = new RelateUserVO();
                    BeanUtils.copyProperties(vo, data);
                    // 判断当前用户是否关联了所传角色
                    data.setRelate(isRelateRole(vo.getId(), roleId));
                    return data;
                }).collect(Collectors.toList());
        result.setRecords(resultList);
        return result;
    }

    private Boolean isRelateRole(Long userId, Long roleId) {
        RelUserRole data = relUserRoleService.selectByKey(userId, roleId);
        if (data == null) {
            return false;
        }
        return true;
    }

    @Override
    public SysUser getUserInfo(String username) {
        SysUser sysUser = baseMapper.getUserInfo(username);
        // 用户不存在
        if (sysUser == null) {
            throw new BusinessException(ResponseCode.USER_NOT_EXIST);
        }
        return sysUser;
    }

    @Override
    public SysUserData getUser(Long id) {
        if (id == null) {
            throw new BusinessException(ResponseCode.PARAM_IS_BLANK);
        }
        SysUserData data = new SysUserData();
        SysUser user = baseMapper.selectById(id);
        if (user == null) {
            throw new BusinessException(ResponseCode.USER_NOT_EXIST);
        }
        data.setUser(user);

        if (user.getDeptId() != null) {
            SysDept sysDept = sysDeptMapper.selectById(user.getDeptId());
            if (sysDept != null) {
                data.setDeptName(sysDept.getDeptName());
            }
        }

        if (user.getPhotoId() != null) {
            String base64 = fileService.getImage(user.getPhotoId());
            data.setFaceUri(base64);
        }
        return data;
    }

    /**
     * 根据用户名，获取用户
     *
     * @param username 用户名
     * @return
     */
    @Override
    public SysUser getByUsername(String username) {
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUser::getUsername, username);
        return baseMapper.selectOne(wrapper);
    }

    @Override
    public SysUser getByPhone(String phone) {
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUser::getPhone, phone);
        return baseMapper.selectOne(wrapper);
    }

    @Override
    public int countUser(Long photoId) {
        return baseMapper.countUser(photoId);
    }

    @Override
    public void export(List<UserVO> list, HttpServletResponse response) {
        List<ExportUserData> resultList = new ArrayList<>();
        if (list.isEmpty()) {
            return;
        }

        try {
            File excelFile = MyFileUtils.createFile("/userData/");
            File imageFile = MyFileUtils.createFile("/userData/images/");

            for (UserVO user : list) {
                ExportUserData data = new ExportUserData();
                BeanUtils.copyProperties(user, data);
                String name = user.getRealName();

                // 根据图片id，获取图片base64字符串
                if (user.getPhotoId() == null) {
                    logger.error("遍历用户列表，当前用户 {} 图片id为空", name);
                    continue;
                }

                /**
                 * 生成jpg图片
                 */
                // 获取文件的base64编码
                String imgBase64 = fileService.getFile(user.getPhotoId());
                String imgName = name + user.getId() + ".jpg";
                String imgPath = imageFile.getPath() + imgName;
                boolean result = MyFileUtils.downloadFile(imgBase64, imgPath);
                if (result) {
                    logger.info("{} 生成jpg图片结果：{}，图片名称为 {}", name, result, imgName);
                    data.setImgName(imgName);
                } else {
                    logger.error("{} 生成jpg图片结果：{}", name, result);
                }

                resultList.add(data);
            }

            /**
             * 生成excel文件
             */
            MyExcelUtils.generateExcel(list, "用户列表", "用户信息", ExportUserData.class, excelFile.getPath() + "users.xlsx");

            /**
             * zip压缩
             */
            ZipUtils.exportZip(response, excelFile.getPath(), "users.zip");

            logger.info("用户数据已导出成功");
        } catch (FileNotFoundException e) {
            logger.error("【捕获异常-创建文件】\r\n异常记录：", e);
        } catch (Exception e) {
            logger.error("【捕获异常-导出Excel】\r\n异常记录：", e);
        }

    }

    @Override
    public void exportAll(HttpServletResponse response) {
        // 获取所有用户列表
        List<UserVO> list = getEnabledUsers(null);
        export(list, response);
    }

}